package com.ruiboyun.liveapp.ui;

import android.util.Log;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

import com.alibaba.livecloud.live.AlivcMediaFormat;
import com.alibaba.livecloud.live.AlivcMediaRecorder;
import com.alibaba.livecloud.live.AlivcMediaRecorderFactory;
import com.alibaba.livecloud.live.AlivcStatusCode;
import com.alibaba.livecloud.live.OnLiveRecordErrorListener;
import com.alibaba.livecloud.live.OnNetworkStatusListener;
import com.alibaba.livecloud.live.OnRecordStatusListener;
import com.ruiboyun.liveapp.base.App;
import com.ruiboyun.liveapp.bean.Channel;
import com.ruiboyun.liveapp.util.tool.Loger;
import com.ruiboyun.liveapp.util.tool.ToasUtil;

import java.util.HashMap;
import java.util.Map;

/**
 * Created by wushiqian on 2017/9/17.
 */

public class LiveManager {
    private static final String TAG = "msg";
    private static LiveManager instance;
    private AlivcMediaRecorder mMediaRecorder;
    private Surface mPreviewSurface;


    private LiveManager() {
    }

    public static LiveManager getInstance() {
        if (instance == null) {
            synchronized (LiveManager.class) {
                if (instance == null) {
                    instance = new LiveManager();

                }
            }
        }
        return instance;
    }

    private Map<String, Object> mConfigure = new HashMap<>();
    private int mPreviewWidth = 0;
    private int mPreviewHeight = 0;
    private String pushUrl;
    private int resolution = AlivcMediaFormat.OUTPUT_RESOLUTION_480P;
    private boolean screenOrientation;
    private int cameraFrontFacing = AlivcMediaFormat.CAMERA_FACING_BACK;
    private int minBitrate = 600;
    private int maxBitrate = 1000;
    private int bestBitrate = 800;
    private int initBitrate = 800;
    private int frameRate = 15;
    private Channel channel;
    private OnLiveListener onLiveListener;

    public void setOnLiveListener(OnLiveListener onLiveListener) {
        this.onLiveListener = onLiveListener;
    }

    public interface OnLiveListener {
        void onError(String msg);
        void onNetBroken();
        void onLive();
    }

    public void init(String pushUrl,Channel channel) {
        this.pushUrl = pushUrl;
        this.channel=channel;
        if (mMediaRecorder == null) {
            mMediaRecorder = AlivcMediaRecorderFactory.createMediaRecorder();
            mMediaRecorder.init(App.getInstance());
            mMediaRecorder.setOnRecordStatusListener(mRecordStatusListener);
            mMediaRecorder.setOnNetworkStatusListener(mOnNetworkStatusListener);
            mMediaRecorder.setOnRecordErrorListener(mOnErrorListener);

            mConfigure.put(AlivcMediaFormat.KEY_CAMERA_FACING, cameraFrontFacing);
            mConfigure.put(AlivcMediaFormat.KEY_OUTPUT_RESOLUTION, channel.getOutput_resolution());

            //音频码率
            mConfigure.put(AlivcMediaFormat.KEY_AUDIO_BITRATE,channel.getBitrate_audio()*1000);
            //最大视频码率
            mConfigure.put(AlivcMediaFormat.KEY_MAX_VIDEO_BITRATE, channel.getBitrate_max() * 1000);
            //最小视频码率
            mConfigure.put(AlivcMediaFormat.KEY_MIN_VIDEO_BITRATE, channel.getBitrate_min() * 1000);
            //最优视频码率
            mConfigure.put(AlivcMediaFormat.KEY_BEST_VIDEO_BITRATE, channel.getBitrate() * 1000);
            //初始视频码率
            mConfigure.put(AlivcMediaFormat.KEY_INITIAL_VIDEO_BITRATE, channel.getBitrate() * 1000);
            mConfigure.put(AlivcMediaFormat.KEY_EXPOSURE_COMPENSATION, -1);//曝光度
            mConfigure.put(AlivcMediaFormat.KEY_FRAME_RATE, channel.getFrame_rate());
            mConfigure.put(AlivcMediaFormat.KEY_DISPLAY_ROTATION, 90);

        }

    }

    private SurfaceView surfaceView;

    public void startPreview(SurfaceView surfaceView) {

        this.surfaceView = surfaceView;
        surfaceView.getHolder().addCallback(surfaceCallback);

    }

    private void preview() {
        mMediaRecorder.prepare(mConfigure, mPreviewSurface);
        mMediaRecorder.setPreviewSize(surfaceView.getMeasuredWidth(), surfaceView.getMeasuredHeight());
        if ((int) mConfigure.get(AlivcMediaFormat.KEY_CAMERA_FACING) == AlivcMediaFormat.CAMERA_FACING_FRONT) {
            mMediaRecorder.addFlag(AlivcMediaFormat.FLAG_BEAUTY_ON);
        }
    }

    private final SurfaceHolder.Callback surfaceCallback = new SurfaceHolder.Callback() {
        @Override
        public void surfaceCreated(SurfaceHolder holder) {
            holder.setKeepScreenOn(true);
            mPreviewSurface = holder.getSurface();
            preview();
        }

        @Override
        public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
            mMediaRecorder.setPreviewSize(width, height);
            mPreviewWidth = width;
            mPreviewHeight = height;
        }

        @Override
        public void surfaceDestroyed(SurfaceHolder holder) {
            mPreviewSurface = null;
            if (mMediaRecorder != null) {
                mMediaRecorder.stopRecord();
                mMediaRecorder.reset();
            }

        }
    };

    boolean prepared;
    private OnRecordStatusListener mRecordStatusListener = new OnRecordStatusListener() {
        @Override
        public void onDeviceAttach() {
            Loger.e("onDeviceAttach");
        }

        @Override
        public void onDeviceAttachFailed(int i) {
            Loger.e("onDeviceAttachFailed" + i);
        }

        @Override
        public void onSessionAttach() {
            prepared = true;
            Loger.e("onSessionAttach");

        }

        @Override
        public void onSessionDetach() {
            prepared = false;
            Loger.e("onSessionDetach");
        }

        @Override
        public void onDeviceDetach() {
            Loger.e("onDeviceDetach");
        }

        @Override
        public void onIllegalOutputResolution() {
            Loger.e("onIllegalOutputResolution");
        }
    };

    private OnNetworkStatusListener mOnNetworkStatusListener = new OnNetworkStatusListener() {
        @Override
        public void onNetworkBusy() {
            if (onLiveListener != null) {
                onLiveListener.onNetBroken();
            }

        }

        @Override
        public void onNetworkFree() {
            Loger.e("onNetworkFree");
        }

        @Override
        public void onConnectionStatusChange(int status) {
            switch (status) {
                case AlivcStatusCode.STATUS_CONNECTION_START:
                    Loger.e("CONNECTION_START");
                    break;
                case AlivcStatusCode.STATUS_CONNECTION_ESTABLISHED:
                    Loger.e("CONNECTION_ESTABLISHED");
                    ToasUtil.showCenterToast("推流成功");
                    if (onLiveListener != null) {
                        onLiveListener.onLive();
                    }
                    break;
                case AlivcStatusCode.STATUS_CONNECTION_CLOSED:
                    Loger.e("CONNECTION_CLOSED");
                    break;

            }
        }


        @Override
        public boolean onNetworkReconnectFailed() {
            Loger.e("onNetworkReconnectFailed");
            return true;
        }
    };
    private OnLiveRecordErrorListener mOnErrorListener = new OnLiveRecordErrorListener() {
        @Override
        public void onError(int errorCode) {
            switch (errorCode) {
                case AlivcStatusCode.ERROR_SERVER_CLOSED_CONNECTION:
                    Log.e(TAG, "ERROR_SERVER_CLOSED_CONNECTION" + errorCode);
                    break;
                case AlivcStatusCode.ERORR_OUT_OF_MEMORY:
                    onLiveListener.onError("直播中断。。。");
                    Log.e(TAG, "ERORR_OUT_OF_MEMORY" + errorCode);
                    break;
                case AlivcStatusCode.ERROR_CONNECTION_TIMEOUT:
                    onLiveListener.onError("直播中断。。。");
                    Log.e(TAG, "ERROR_CONNECTION_TIMEOUT" + errorCode);
                    break;
                case AlivcStatusCode.ERROR_BROKEN_PIPE:
                    ToasUtil.showCenterToast("推流异常");
                    onLiveListener.onError("直播中断。。。");
                    Log.e(TAG, "ERROR_BROKEN_PIPE" + errorCode);
                    break;
                case AlivcStatusCode.ERROR_ILLEGAL_ARGUMENT:
                    Log.e(TAG, "ERROR_ILLEGAL_ARGUMENT" + errorCode);
                    break;
                case AlivcStatusCode.ERROR_IO:
                    onLiveListener.onError("直播中断。。。");
                    Log.e(TAG, "ERROR_IO" + errorCode);

                    break;
                case AlivcStatusCode.ERROR_NETWORK_UNREACHABLE:
                    onLiveListener.onError("直播中断。。。");
                    Log.e(TAG, "Live stream connection error-->" + errorCode);
                    ToasUtil.showCenterToast("网络异常，请检查网络");
                    break;
                default:
                    onLiveListener.onError("直播中断。。。");
                    Log.e(TAG, "default" + errorCode);
                    break;
            }
        }
    };

    public void startLive(String pushUrl) {
        this.pushUrl = pushUrl;
        if (mMediaRecorder != null) {
            mMediaRecorder.startRecord(pushUrl);
        }
    }

    public void switchCamera() {
        if (mMediaRecorder != null) {
            //Demo默认为前置摄像头
            mMediaRecorder.switchCamera();
        }

    }

    public void switchBeauty(boolean beauty) {
        if (mMediaRecorder != null) {
            if (beauty) {
                mMediaRecorder.addFlag(AlivcMediaFormat.FLAG_BEAUTY_ON);//开启美颜
            } else {
                mMediaRecorder.removeFlag(AlivcMediaFormat.FLAG_BEAUTY_ON);//关闭美颜
            }
        }


    }

    public void openFlash() {
        if (mMediaRecorder != null) {

        }
    }

    public void reset() {
        if (mMediaRecorder != null) {
            mMediaRecorder.stopRecord();    //结束推流
            mMediaRecorder.reset();         //释放预览资源
            mMediaRecorder.release();       //释放推流资源
            mMediaRecorder = null;
        }
    }

    public void stopLive() {
        if (mMediaRecorder != null) {
            mMediaRecorder.stopRecord();    //结束推流

        }

    }

    public void autoFocus(float x, float y) {
        if (mMediaRecorder != null) {
            mMediaRecorder.autoFocus(x, y);    //自动对焦

        }
    }
}
